////////////////////////////////////////////////
// DESCRIPTION:
//     Class for loading and manipulating 
//     Installable ISRs
//
// Legal Notices:
//     Copyright (c) 2008, Telliam Consulting, LLC.
//     All rights reserved.
//
//     Redistribution and use in source and binary forms, with or without modification,
//     are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//
//     * Neither the name of Telliam Consulting nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// Disclaimer:
//     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//     IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
//     OF THE POSSIBILITY OF SUCH DAMAGE.  
//
#pragma once

namespace FusionWare
{
	namespace DFX
	{        
		// Implements common setup and initialization of shared interrupt 
        // handling for an Installable Interrupt Service Routine (IISR).
        class ISRChainHandler
        {
        public:
            ISRChainHandler();
            virtual ~ISRChainHandler() { Unload(); }

            /////////////////////////////////////////////////////////////////////
            // Description:
            //    Loads the Insatllable ISR DLL if indicated by the 
            //    RegInfo.
            //
            // Input:
            //    pIsrDll     - name of the DLL
            //    pIsrHandler - name of the ISR Handler function in the DLL
            //    SysIntr     - SYSINTR value for the ISR to use
            //    Irq         - IrqNumber for the ISR
            //    pIsrInfo    - ISR info to pass to the ISR (See remarks for details)
            //    IsrInfoSize - size of pIsrInfo buffer 
            //
            // Remarks:
            //    SYSINTR is passed to the ISR dll via the FusionWare defined
            //    IOCTL_IISR_SYSINTR if that fails then the MS defined
            //    IOCTL_GIISR_INFO. When using IOCTL_GIISR_INFO then the
            //    pIsrInfo MUST point to a GIISRINFO structure. In other cases
            //    any ISR specifc data is valid as FusionWare has seperated the
            //    SYSINTR information to a single control code that is used for all
            //    of the ISRs.
            //
            bool ISRChainHandler::Load( const TCHAR* pIsrDLL
                                      , const TCHAR* pIsrHandler
                                      , UINT32 SysIntr
                                      , UINT32 Irq
                                      , void* pIsrInfo = NULL
                                      , UINT32 IsrInfoSize = 0);

            /////////////////////////////////////////////////////////////////////
            // Description:
            //    Unloads the Insatllable ISR DLL if it was loaded.
            //
            // Returns:
            //    TRUE if no error occured in the process.
            //
            // Remarks:
            //    Returns TRUE even if the RegInfo indicates no DLL to load
            //
            bool Unload();

            // Determines if an Installable ISR was actually loaded.
            bool IsLoaded() { return this->hChainHandler != INVALID_HANDLE_VALUE; }

            // Full IoControl version
            bool IoControl( DWORD IoControlCode
                          , void* pInBuffer
                          , DWORD InBufferSize
                          , void* pOutBuffer
                          , DWORD OutBufferSize
                          , DWORD* pBytesReturned );

            // "Put" only variation
            bool IoControl( DWORD IoControlCode
                          , void* pInBuffer
                          , DWORD InBufferSize);

            // "Get" only variation
            bool IoControl( DWORD IoControlCode
                          , void* pOutBuffer
                          , DWORD OutBufferSize
                          , DWORD* pBytesReturned);

            // "Command" only variation
            bool IoControl(DWORD IoControlCode);
        
        protected:
            HANDLE hChainHandler;

        };

        inline bool ISRChainHandler::IoControl( DWORD IoControlCode
                                              , void* pInBuffer
                                              , DWORD InBufferSize
                                              , void* pOutBuffer
                                              , DWORD OutBufferSize
                                              , DWORD* pBytesReturned)
        {
            return 0!=KernelLibIoControl( this->hChainHandler
                                        , IoControlCode
                                        , pInBuffer
                                        , InBufferSize
                                        , pOutBuffer
                                        , OutBufferSize
                                        , pBytesReturned);
        }

        inline bool ISRChainHandler::IoControl( DWORD IoControlCode
                                              , void* pInBuffer
                                              , DWORD InBufferSize)
        {
            DWORD dwActual;
            return IoControl( IoControlCode
                            , pInBuffer
                            , InBufferSize
                            , NULL
                            , 0
                            , &dwActual);
        }

        inline bool ISRChainHandler::IoControl( DWORD IoControlCode
                                              , void* pOutBuffer
                                              , DWORD OutBufferSize
                                              , DWORD* pBytesReturned)
        {
            return IoControl( IoControlCode
                            , NULL
                            , 0
                            , pOutBuffer
                            , OutBufferSize
                            , pBytesReturned);
        }

        inline bool ISRChainHandler::IoControl(DWORD IoControlCode)
        {
            DWORD dwActual;
            return IoControl( IoControlCode
                            , NULL
                            , 0
                            , NULL
                            , 0
                            , &dwActual);
        }
	}
}